package com.my.service.impl;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.mapping.StatementType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.stereotype.Service;

import com.my.service.DbService;
import com.my.util.LogUtil;

@Service
public class DbServiceImpl implements DbService {
	private SqlSessionFactory factory;
	private SqlSession session;

	public SqlSessionFactory getFactory() {
		return factory;
	}

	public void setFactory(SqlSessionFactory factory) {
		this.factory = factory;
	}

	
	private SqlSession getSession() {
		return factory.openSession();
	}

	private void closeSession() {
		if (session != null) {
			session.close();
			session = null;
		}
	}

	
	private void logException(Exception e, String mapperId) {
		String msg = "SQL语句执行出错！Mybatis配置ID:" + mapperId;
		LogUtil.getLogger().error(msg, e);
	}
	@SuppressWarnings("unchecked")
	@Override
	public <T> List<T> selectList(String mapperId, Object param){
		List<?> list = null;
		try {
			session = getSession();
			long now = System.currentTimeMillis();
			if (param != null) {
					list = session.selectList(mapperId, param);
			} else {
					list = session.selectList(mapperId);
			}
			SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd H:m:s.S");
			System.out.println("sqlId:" + mapperId + ", cost:"
					+ ((System.currentTimeMillis() - now) / 1000.0)
					+ "s, endTime:" + format.format(new Date()));
		} catch (Exception e) {
			logException(e, mapperId);
		} finally {
			closeSession();
		}
		return (List<T>) list;
	}


	@Override
	public <T> List<T> selectList(String mapperId){
		return selectList(mapperId, null);
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> T selectOne(String mapperId, Object param){
		Object obj = null;
		try {
			session = getSession();
			if (param != null) {
				obj = session.selectOne(mapperId, param);
			} else {
				obj = session.selectOne(mapperId);
			}
		} catch (Exception e) {
			logException(e, mapperId);
		} finally {
			closeSession();
		}
		return (T) obj;
	}

	@Override
	public <T> T selectOne(String mapperId){
		return selectOne(mapperId, null);
	}

	@Override
	public void modify(String mapperId, Object param){
		try {
			session = getSession();
			SqlCommandType type = session.getConfiguration()
					.getMappedStatement(mapperId).getSqlCommandType();
			StatementType stmtType = session.getConfiguration()
					.getMappedStatement(mapperId).getStatementType();
			if (type.equals(SqlCommandType.INSERT)) {
				if (param instanceof List<?>) { // 一组参数
					List<?> list = (List<?>) param;
					for (Object obj : list)
						session.insert(mapperId, obj);
				} else {
					session.insert(mapperId, param);
				}
			} else if (type.equals(SqlCommandType.UPDATE)) {
				if (param instanceof List<?>) { // 一组参数
					List<?> list = (List<?>) param;
					for (Object obj : list)
						session.update(mapperId, obj);
				} else {
					session.update(mapperId, param);
				}
			} else if (type.equals(SqlCommandType.DELETE)) {
				if (param instanceof List<?>) { // 一组参数
					List<?> list = (List<?>) param;
					for (Object obj : list)
						session.delete(mapperId, obj);
				} else {
					session.delete(mapperId, param);
				}
			} else if (type.equals(SqlCommandType.SELECT)
					&& stmtType.equals(StatementType.CALLABLE)) { // 存过
				if (param instanceof List<?>) { // 一组参数
					List<?> list = (List<?>) param;
					for (Object obj : list)
						session.selectOne(mapperId, obj);
				} else {
					session.selectOne(mapperId, param);
				}
			}
		} catch (Exception e) {
			logException(e, mapperId);
		} finally {
			closeSession();
		}
	}

	@Override
	public void modify(String mapperId){
		modify(mapperId, null);
	}

	@Override
	public void modify(String[] mapperId, Object param){
		if (param instanceof List<?>) { // 一组参数
			List<?> list = (List<?>) param;
			if (mapperId.length != list.size()) // sql组与参数组数量不匹配
				return;
			for (int i = 0; i < mapperId.length; i++)
				modify(mapperId[i], list.get(i));
		} else {
			for (int i = 0; i < mapperId.length; i++)
				modify(mapperId[i], param);
		}
	}

	@Override
	public void modify(Object mapperId, Object param){
		if (mapperId instanceof List<?>) { //多个sql
			List<?> sqls = (List<?>) mapperId;
			if (param instanceof List<?>) { //多个传参
				List<?> params = (List<?>) param;
				if (sqls.size() != params.size()) // sql组与参数组数量不匹配
					return;
				for (int i = 0; i < sqls.size(); i++)
					modify(sqls.get(i), params.get(i));
			} else {
				modify((String[]) sqls.toArray(new String[sqls.size()]), param);
			}
		} else { //只有一个sql
			modify(mapperId.toString(), param);
		}
	}

	@Override
	public void modify(String mapperId, String param){
		if (mapperId.startsWith("[")) { // 多语句执行
			JSONArray arr = JSONArray.fromObject(mapperId);
			String[] sqls = (String[]) arr.toArray(new String[arr.size()]);
			if (param != null && !param.equals("")) {
				if (param.startsWith("["))
					modify(sqls, JSONArray.fromObject(param)); // 多语句多传参，每个sql对应一组参数
				else
					modify(sqls, JSONObject.fromObject(param)); // 多语句单传参，所有sql执行相同传参
			} else
				modify(sqls); // 多语句无传参
		} else { // 单语句执行
			if (param != null && !param.equals(""))
				if (param.startsWith("["))
					modify(mapperId, JSONArray.fromObject(param)); // 单语句多传参
				else
					modify(mapperId, JSONObject.fromObject(param)); // 单语句单传参
			else
				modify(mapperId); // 单语句无传参
		}
	}

	@Override
	public void modify(String[] mapperId){
		for (int i = 0; i < mapperId.length; i++)
			modify(mapperId[i]);
	}

	@Override
	public void execProc(String mapperId, Object param){
		try {
			session = getSession();
			if (param != null) {
				if (param instanceof List<?>) { // 一组参数
					List<?> list = (List<?>) param;
					for (Object obj : list)
						session.selectOne(mapperId, obj);
				} else {
					session.selectOne(mapperId, param);
				}
			} else {
				session.selectOne(mapperId);
			}
		} catch (Exception e) {
			logException(e, mapperId);
		} finally {
			closeSession();
		}
	}

	@Override
	public void execProc(String mapperId){
		execProc(mapperId, null);
	}

	@Override
	public void execProc(String[] mapperId, Object param){
		if (param instanceof List<?>) { // 一组参数
			List<?> list = (List<?>) param;
			if (mapperId.length != list.size()) // sql组与参数组数量不匹配
				return;
			for (int i = 0; i < mapperId.length; i++)
				execProc(mapperId[i], list.get(i));
		} else {
			for (int i = 0; i < mapperId.length; i++)
				execProc(mapperId[i], param);
		}
	}

	@Override
	public void execProc(String[] mapperId){
		for (int i = 0; i < mapperId.length; i++)
			execProc(mapperId[i]);
	}
}
